﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using OpenQuarters.WebQuarters.Utils;
using OpenQuarters.WebQuarters.Core;
using System.IO;
using System.Web.Mvc;

namespace OpenQuarters.WebQuarters.Modules.Core
{
    public class LoginViewData
    {
        public User User { get; set; }
        public LoginModule Module { get; set; }
    }

    public class LoginModule : Module
    {
        public static Dictionary<string, string> Templates
        {
            get
            {
                var d = new Dictionary<string, string>();
                d.Add("", "[None]");
                foreach (var dir in new DirectoryInfo(Oracle.Context.Server.MapPath("~/Templates/")).GetDirectories())
                {
                    if (dir.Name.Contains(typeof(LoginModule).FullName))
                    {
                        foreach (var template in dir.GetFiles("*.ascx", SearchOption.TopDirectoryOnly))
                        {
                            d.Add(template.Name.Replace(".ascx", ""), template.Name.Replace(".ascx", ""));
                        }
                    }
                }
                return d;
            }
        }

        private string template = "";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.DropDown, OptionSource = "OpenQuarters.WebQuarters.Modules.Core.LoginModule.Templates")]
        public string Template
        {
            get { return template; }
            set { template = value; }
        }

        public enum LoginModuleLogOutDisplayType
        {
            None,
            Link,
            Button
        }

        private LoginModuleLogOutDisplayType display_Log_Out_as = LoginModuleLogOutDisplayType.Button;

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.DropDown)]
        public LoginModuleLogOutDisplayType Display_Log_Out_as
        {
            get { return display_Log_Out_as; }
            set { display_Log_Out_as = value; }
        }

        private bool display_Form = true;

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.CheckBox)]
        public bool Display_Form
        {
            get { return display_Form; }
            set { display_Form = value; }
        }

        private string return_Url = "";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.TextBox)]
        public string Return_Url
        {
            get { return return_Url; }
            set { return_Url = value; }
        }

        public LoginModule()
        {
        }

        public override void Initialise()
        {
            this.ModuleName = "Login Module";
            this.ModuleDescription = "Places a login form on the page.";
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            if (!string.IsNullOrEmpty(this.template))
            {
                LoginViewData viewData = new LoginViewData();
                viewData.User = User.Current;
                viewData.Module = this;

                var viewPath = "~/Templates/" + this.GetType().FullName + "/" + this.Template + ".ascx";
                //this.Controls.AddLiteral(GeneralUtils.RenderViewToString(
                //        Oracle.CurrentControllerContext,
                //        viewPath,
                //        null,
                //        new ViewDataDictionary(viewData),
                //        new TempDataDictionary()));
                this.Controls.AddLiteral(GeneralUtils.RenderPartialToString(viewPath, viewData));
            }
            else
            {
                var translations = Translation.Get(new string[]
                {
                    "You_are_currently_logged_in_as",
                    "Log_out",
                    "Login"
                }.ToList());

                    if (User.Current.IsAuthenticated)
                    {
                        this.Controls.AddLiteral("<p>" + translations["You_are_currently_logged_in_as"] + ": " + User.Current.UserId + "</p>");
                        this.Controls.AddLiteral(@"
    <form action=""/cms/account/logout/"" method=""post"">
        <p>
            ");

                        switch (this.Display_Log_Out_as)
                        {
                            case LoginModuleLogOutDisplayType.Button:
                                this.Controls.AddLiteral(@"<input type=""submit"" value=""" + translations["Log_out"] + @""" />");
                                break;
                            case LoginModuleLogOutDisplayType.Link:
                                this.Controls.AddLiteral(@"<a href=""javascript:void(0);"" onclick=""$(this).parents('form:first').submit();"">" + translations["Log_out"] + @"</a>");
                                break;
                        }

                        this.Controls.AddLiteral(@"
        </p>
    </form>");
                    }
                    else
                    {
                        if (display_Form)
                        {
                            if (System.IO.File.Exists(Server.MapPath("/Forms/Login.tpl")))
                            {
                                this.Controls.Add(new JForm("Login", "/cms/account/login?ReturnUrl=" + Server.UrlEncode((!string.IsNullOrEmpty(return_Url) ? return_Url : User.Current.LastFailedURL)))
                            {
                                UseJavaScript = false,
                                //OnSuccessScript = "window.location = '" + Server.UrlEncode((!string.IsNullOrEmpty(return_Url) ? return_Url : User.Current.LastFailedURL)) + "';"
                            });
                            }
                            else
                            {
                                this.Controls.Add(new JForm("OpenQuarters.WebQuarters.Modules.Core,Resources.Login.Login.tpl", JForm.TemplateType.EmbeddedResource, "/cms/account/login?ReturnUrl=" + Server.UrlEncode((!string.IsNullOrEmpty(return_Url) ? return_Url : User.Current.LastFailedURL)))
                                {
                                    UseJavaScript = false,
                                    //OnSuccessScript = "window.location = '" + Server.UrlEncode((!string.IsNullOrEmpty(return_Url) ? return_Url : User.Current.LastFailedURL)) + "';"
                                });
                            }


                        }
                        else
                        {
                            this.Controls.AddLiteral(@"
    <form action=""" + CMSPage.LoginPage.GetUrl() + "?ReturnUrl=" + Server.UrlEncode(!string.IsNullOrEmpty(return_Url) ? return_Url : User.Current.LastFailedURL) + @""" method=""post"">
        <p>
            ");

                            switch (this.Display_Log_Out_as)
                            {
                                case LoginModuleLogOutDisplayType.Button:
                                    this.Controls.AddLiteral(@"<input type=""submit"" value=""" + translations["Login"] + @""" />");
                                    break;
                                case LoginModuleLogOutDisplayType.Link:
                                    this.Controls.AddLiteral(@"<a href=""" + CMSPage.LoginPage.GetUrl() + "?ReturnUrl=" + Server.UrlEncode(!string.IsNullOrEmpty(return_Url) ? return_Url : User.Current.LastFailedURL) + @""">" + translations["Login"] + @"</a>");
                                    break;
                            }

                            this.Controls.AddLiteral(@"
        </p>
    </form>");
                    }
                }
            }
        }

        [Invokable]
        public static JFormResponse<User> LoginHandler(HttpRequest request)
        {
            var formResponse = new JFormResponse<User>();

            var username = request.Form["Username"];
            var password = request.Form["Password"];

            if (username == null || username.Length == 0)
            {
                formResponse.errorMessages[""].Add(Translation.Translate("Please_enter_your_username"));
            }
            if (password == null || password.Length == 0)
            {
                formResponse.errorMessages[""].Add(Translation.Translate("Please_enter_your_password"));
            }

            if (formResponse.errorMessages.Count == 0)
            {
                // TODO: Count login attempts, disable account after x failed attempts
                if (User.Current.Login(username, password))
                {
                    // TODO: Reset login attempts to 0
                    formResponse.result = User.Current;
                    User.Current.LastFailedURL = "";
                }
                else
                {
                    formResponse.errorMessages[""].Add(Translation.Translate("The_details_provided_are_not_valid,_please_try_again"));
                }
            }

            return formResponse;

        }
    }
}
